﻿using FishSimulation.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Input;
using Timer = System.Timers.Timer;

namespace FishSimulation.Views {
    /// <summary>
    /// Interaction logic for WorldView.xaml
    /// </summary>
    public partial class WorldView : ViewBase
    {
        #region Members
        List<Actor> deaths = new List<Actor>();
        List<Actor> offspring = new List<Actor>();
        bool ignoreTimer = false;
        Timer timer = new Timer();
        TaskScheduler uiContext = null;
        #endregion

        #region Properties
        public double Delay {
            get { return timer.Interval; }
            set { timer.Interval = value; }
        }

        public bool Playing
        {
            get { return timer.Enabled; }
            set { timer.Enabled = value; }
        }
        #endregion

        #region Constructors
        public WorldView() {
            InitializeComponent();

            uiContext = TaskScheduler.FromCurrentSynchronizationContext();
            
            timer.Interval = 1000;
            timer.Enabled = false;
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
        }
        #endregion        

        #region Event Handlers
        private void actor_Mated(Actor actor, Actor.MatedEventArgs e)
        {
            this.offspring.AddRange(e.OffSpring);
        }

        private void actor_Died(Actor actor)
        {
            this.deaths.Add(actor);
        }

        private void timer_Elapsed(object sender, ElapsedEventArgs e) {
            if(ignoreTimer) return;
            Task.Factory.StartNew(() => { this.OnElapsed(); }, CancellationToken.None, TaskCreationOptions.None, uiContext);            
        }       

        private void pond_ViewBaseClicked(ViewBase sender, MouseButtonEventArgs e)
        {
            this.OnViewBaseClicked(sender, e);
        }

        private void ZoomControl_MouseUp(object sender, MouseButtonEventArgs e)
        {
            //this is a hack. couldn't get mouse up to fire on pondview
            pond.OnMouseUp(e);
        }
        #endregion

        #region Methods
        public void BindPond()
        {
            this.pond.Bind();
        }

        private void OnElapsed()
        {
            try
            {
                ignoreTimer = true;
                timer.Stop();
                Repository.Instance.World.Ticks += (long)timer.Interval;
                deaths.Clear();
                offspring.Clear();

                //timer.Enabled = false;
                //Repository.Instance.World.Actors.AsParallel().ForAll(                
                Repository.Instance.World.Actors.ToList().ForEach(
                    delegate(Actor actor)
                    {
                        actor.Died += new Actor.ActionEventHandler(actor_Died);
                        actor.Mated += new Actor.MatedEventHandler(actor_Mated);
                        actor.Move();
                        actor.Died -= actor_Died;
                        actor.Mated -= actor_Mated;
                    }
                );

                deaths.ForEach(x => Repository.Instance.World.Actors.Remove(x));
                foreach (var a in this.offspring)
                    Repository.Instance.World.Actors.Add(a);

                var action = new Action(pond.Bind);
                this.Dispatcher.Invoke(action);
            }
            finally
            {
                timer.Start();
                ignoreTimer = false;
            }
        }
        #endregion
    }
}
